package cn.buddha.jesj.lambda.functionInterface.jdk8;

import org.springframework.util.StringUtils;

import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

//import java.util.function.*;

/**
 * @ClassName Jdk8FunctionInterfaceTest
 * @Author 友野浩二
 * @Description jdk8自带函数式接口测试
 * @Version 1.0
 *
 * <pre>
 * JavaSE 8新增了一个包: java.util.function，包含了常用的函数式接口
 *      Consumer<T>       --> 接收T对象，不返回值
 *      Supplier<T>       --> 提供T对象(例如工厂)，不接收值
 *      Function<T, R>    --> 接收T对象，返回R对象
 *      Predicate<T>      --> 接收T对象并返回boolean
 *      UnaryOperator<T>  --> 接收T对象，返回T对象
 *      BinaryOperator<T> --> 接收两个T对象，返回T对象
 * </pre>
 */
public class Jdk8FunctionInterfaceTest {

    public static void main(String[] args) {
        function();// JDK8 提供的常用函数式接口
        methodRef();// 方法引用
    }

    private static void function() {
        System.out.println("<<<<======== JDK8 提供的常用函数式接口 ========>>>>");
        // 1- 消费性接口，有参无返回值
        Consumer<String> consumer = str -> System.out.println("消费性接口,有参无返回值: ".concat(str));
        consumer.accept("彤彤");

        // 2- 供给型接口，无参有返回值
        Supplier<Integer> supplier = () -> 9999999;
        System.out.println("供给型接口,无参有返回值: " + supplier.get());

        // 3- 函数式接口，有参有返回值
        Function<Integer, Double> function = a -> a * 2.23;
        System.out.println("函数式接口,有参有返回值: " + function.apply(3));

        // 4- 断言型接口，有参有返回值，返回值是boolean类型
        Predicate<String> predicate = str -> !StringUtils.isEmpty(str) && "a".equals(str);
        System.out.println("断言型接口,有参有返回值,返回值是boolean类型: " + predicate.test("a"));
    }

    // 方法引用: 如果lambda表达式的body体内容已经有方法实现了，那么就可以使用“方法引用”
    private static void methodRef() {
        System.out.println("<<<<======== 方法引用 ========>>>>");

        // 1- 静态方法引用 -> 类::静态方法名(ClassName::methodName)
        BiFunction<Integer, Integer, Integer> biFunLambda = (x, y) -> Integer.compare(x, y);
        System.out.println("lambda表达式: " + biFunLambda.apply(10, 20));

        BiFunction<Integer, Integer, Integer> biFunMethRef = Integer::compare;
        System.out.println("静态方法引用: " + biFunMethRef.apply(10, 20));

        // 2- 实例上的实例方法引用 -> 对象::实例方法名(instanceReference::methodName)
        FunctionRef functionRef = FunctionRef.builder().build();
        BiFunction<Integer, Integer, Integer> biFunction = (a, b) -> functionRef.fun(a, b);
        System.out.println("lambda表达式: " + biFunction.apply(10, 20));

        BiFunction<Integer, Integer, Integer> biFunInstanceRef = functionRef::fun;
        System.out.println("实例上的实例方法引用: " + biFunInstanceRef.apply(10, 20));

        // 3- 类型上的实例方法引用 -> 类::实例方法名(ClassName::methodName)

        // 4- 构造方法引用 Class::new
        Supplier<FunctionRef> supplier = () -> new FunctionRef();
        Supplier<FunctionRef> supplier1 = FunctionRef::new;
        System.out.println("构造方法引用: " + supplier1.get());
    }

}
